

class HmmSubject(object):
    def __init__(self, sArgSubject):
        self.aProbSt = [];
        self.aStates = [];
        self.aMaxSts = [];
        self.aTimes = [];
        self.sArgSubject = sArgSubject;
    
    def getStates(self, sTime, aActs_Time):
        aSt = [];
        for actM in aActs_Time[sTime]:
            for sArg in actM.rootAct.aSubjects:
                if sArg == self.sArgSubject:
                    aSt.append(actM);
        self.aStates.append(aSt);
        
    def getNullSt(self, iT, graph):
        nNullProb = 1.0;
        for actM in self.aStates[iT]: #Update Prob on each Value-Act (of this Time Step)
            node = graph.idndict[actM.sId];
            nObsProb = 1;
            for i in range(len(self.aStates[iT])): #Likelihood of each Obs given this Value-Act
                nObsProb *= 0.1; #Change 0.1 to Null Prob Model: P(Obs|~M)
            nSumProb = 0;
            nLinks = len(graph.ndict[node][0]);
            if nLinks==0:
                print "  -NULL-Prior Prob:", (1-graph.ndict[node][1][0]);
                nSumProb += (1-graph.ndict[node][1][0]);
            elif nLinks>0:
                print "  -NULL-Transition Probs:";
                for i in range(len(graph.ndict[node][0])): #TEMPORARLY (later consider links that doesn't have sArgSubject)
                    print "  -PastSt:", graph.ndict[node][0][i].name, "Trans_Prob:", (1-graph.ndict[node][1][2**i]);
                    nSumProb += (1-graph.ndict[node][1][2**i]) * graph.ndict[node][0][i].nHmmProb;
            nNullProb *= (nObsProb * nSumProb);
        return nNullProb;
        
    
    def getProbSt(self, iT, graph):
        print "\nTime:", self.aTimes[iT], "- HMM:", self.sArgSubject;
        aProbSt_T = [];
        for actM in self.aStates[iT]: #Update Prob on each Value-Act (of this Time Step)
            node = graph.idndict[actM.sId];
            print "State:", actM.rootAct.name;
            nObsProb = 1;
            for i in range(len(self.aStates[iT])): #Likelihood of each Obs given this Value-Act
                if self.aStates[iT][i]==actM:
#                    print "  -Likelihood:", actM.nLikelihood;
                    nObsProb *= actM.nLikelihood;
                else:
#                    print "  -Null Likelihood:", 0.1;
                    nObsProb *= 0.1; #Change 0.1 to Null Prob Model: P(Obs|~M)
            nSumProb = 0;
            nLinks = len(graph.ndict[node][0]);
            if nLinks==0:
                print "  -Prior Prob:", graph.ndict[node][1][0];
                nSumProb += graph.ndict[node][1][0];
            elif nLinks>0:
                print "  -Transition Probs:", graph.ndict[node][1];
                for i in range(len(graph.ndict[node][0])): #TEMPORARLY (later consider links that doesn't have sArgSubject)
                    print "  -PastSt:", graph.ndict[node][0][i].name, "Trans_Prob:", graph.ndict[node][1][2**i];
#                    nSumProb += graph.ndict[node][1][2**i] * self.aProbSt[iT-1][i];
                    nSumProb += graph.ndict[node][1][2**i] * graph.ndict[node][0][i].nHmmProb;
            aProbSt_T.append(nObsProb * nSumProb);
        aProbSt_T.append(self.getNullSt(iT, graph));
        nZ = 1.0/sum(aProbSt_T); #Normalization Constant
        for i in range(len(aProbSt_T)): #Normalize Probs
            aProbSt_T[i] *= nZ;
        self.aProbSt.append(aProbSt_T);
        for i, actM in enumerate(self.aStates[iT]): #Store these Probs into their Nodes
            actM.rootAct.nHmmProb = aProbSt_T[i];
        print "ProbSt[iT]:", self.aProbSt[iT];
    
    def getMaxProbSt(self, iT, graph):
        pass;
#        iAct = 0;
#        aProbSt_T = [];
#        for actM in self.aStates[iT]: #Update Prob on each Value-Act (of this Time Step)
#            node = graph.idndict[actM.sId];
#            nObsProb = 1;
#            for i in range(len(self.aStates[iT])): #Likelihood of each Obs given this Value-Act
#                if self.aStates[iT][i]==actM:
#                    nObsProb *= actM.nLikelihood;
#                else:
#                    nObsProb *= 0.1; #Change 0.1 to Null Prob Model: P(Obs|~M)
#            if iT==0:
#                nMaxSumProb = actM.nPrior; #Might be better to use the Marginalization                
#            elif iT>0:
#                aSumProb = [];
#                for i in range(len(graph.ndict[node][0])): #TEMPORARLY (later consider links that doesn't have sArgSubject)
#                    aSumProb.append(graph.ndict[node][1][2**i] * max(self.aProbSt[iT-1]));
#                nMaxSumProb = max(aSumProb);
#            aProbSt_T.append(nObsProb * nMaxSumProb);
#            iAct += 1;        
#        nZ = 1.0/sum(aProbSt_T); #Normalization Constant
#        for i in range(len(aProbSt_T)): #Normalize Probs
#            aProbSt_T[i] *= nZ;
#        self.aMaxSts.append(aProbSt_T.index(max(aProbSt_T)));
#        print "MaxSts[iT]:", self.aMaxSts;
    
    def updateHmm(self, sTime, aActs_Time, graph):
        self.aTimes.append(sTime);
        self.getStates(sTime, aActs_Time);
        self.getProbSt(len(self.aTimes)-1, graph);
        self.getMaxProbSt(len(self.aTimes)-1, graph);
        